import numpy as np
import torch
from sklearn.metrics.pairwise import cosine_similarity


def MaxMinNormalization(x, Max, Min):
    """离差标准化，使结果值映射到[0 - 1]之间"""
    x = (x - Min) / (Max - Min)
    return x


def Z_ScoreNormalization(x, mu, sigma):
    """经过处理的数据符合标准正态分布，即均值为0，标准差为1，这里的关键在于复合标准正态分布，个人认为在一定程度上改变了特征的分布"""
    x = (x - mu) / sigma
    return x


def theta_sim(theta_vec, norm_mode=None):
    len = theta_vec.size()[0]
    re = []
    for i in range(0, len - 1):
        for j in range(i + 1, len):
            _ = torch.cosine_similarity(theta_vec[i], theta_vec[j], dim=0)
            re.append(_)
    re_tensor = torch.Tensor(re)
    if norm_mode == "Z_ScoreNormalization":
        sigma = torch.std(re_tensor)
        mu = torch.mean(re_tensor)
        re_Z_Score = []
        for x in re:
            re_Z_Score.append(Z_ScoreNormalization(x=x, mu=mu, sigma=sigma))
        return re_Z_Score
    elif norm_mode == 'MaxMinNormalization':
        max = torch.max(re_tensor)
        min = torch.min(re_tensor)
        re_MaxMi = []
        for x in re:
            re_MaxMi.append(MaxMinNormalization(x=x, Max=max, Min=min))
        return re_MaxMi
    else:
        return re


def sbert_sim(sbert_vec, norm_mode=None):
    sbert_vec_np = cosine_similarity(sbert_vec)
    len = sbert_vec_np[0].size
    re = []
    for i in range(0, len - 1):
        for j in range(i + 1, len):
            re.append(torch.tensor(sbert_vec_np[i, j]))
    re_np = np.array(re)
    if norm_mode == "Z_ScoreNormalization":
        sigma = np.std(re_np)
        mu = np.mean(re_np)
        re_Z_Score = []
        for x in re_np:
            re_Z_Score.append(torch.tensor(Z_ScoreNormalization(x=x, mu=mu, sigma=sigma)))
        return re_Z_Score
    elif norm_mode == 'MaxMinNormalization':
        max = np.max(re_np)
        min = np.min(re_np)
        re_MaxMi = []
        for x in re_np:
            re_MaxMi.append(torch.tensor(MaxMinNormalization(x=x, Max=max, Min=min)))
        return re_MaxMi
    else:
        return re
